home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
VIVIDUS
/
QD3D.SIT
/
qd3d
/
Cqd3dPort.c
next >
Wrap
C/C++ Source or Header
|
1991-10-06
|
24KB
|
1,055 lines
#include "Cqd3dPort.h"
#include "Qd3dErr.h"
#include <math.h>
#include <SANE.h> // For x80<>x96
#include <Traps.h>
#include <TrapTest.h>
#include <Exceptions.h>
/* ======================================================================
Cqd3dPort primitive three dimensional routine library.
This is part of the qd3d Vividus Source Code Library. See the
extern qd3d.doc documentation file for usage. See individual
routines for routine documentation.
Copyright 1991 by Vividus Consulting.
This is not public domain source code. You may not copy and
paste from this source code. Read your Vividus Licensing
agreement for details and other restrictions.
====================================================================== */
Cqd3dPort *the3dPort; /* Present 3d Port set by Set3dPort */
unsigned int *theZBuff; /* ZBuff for the3dPort (if being used) */
unsigned int *theZBuffLast;
unsigned int theZBuffWidth;
static
linmap(
double a1,
double a2,
double b1,
double b2,
double *m,
double *b)
/*
This sets m and b so as to provide a linear mapping from the
parametric line segment a1->a2 to the line segment b1->b2.
Use m & b such that:
newparm = m * oldparm + b.
Note that b2 may be < b1 and a2 < a1. It simply doesn't matter.
*/
{
double am = a2 - a1;
double bm = b2 - b1;
*m = bm / am;
*b = b1 - a1 * bm / am;
}
/* ============================================================ */
/* Access methods: */
void Cqd3dPort::Init()
/*
Initialize this 3dPort to default values.
*/
{
vector a = {.5, .5, .5};
zbuff = zbufflast = NULL;
gw = NULL;
gp = NULL;
onlyqd = cullbacks = usezbuff = usedepthque = false;
lastError = noErr;
onlyqd = true;
wireframe = false;
SetPolarView(&a, 10.0, PI/4.0, 60.0 * PI / 180.0, 0.0);
}
void Cqd3dPort::Dispose(void)
{
DisposPtr(this);
}
void Cqd3dPort::SetQDEnviron(void)
/*
Tell this 3dPort to remember its 2d Quickdraw environment.
Remember, call this method just AFTER setting the current QuickDraw
grafport (with SetPort or SetGWorld) to that which is to contain the
three dimensional image. The current Quickdraw port is stored so
that Set3dPort will automatically call the Quickdraw SetPort() /
SetGWorld().
*/
{
GDHandle gd;
gw = NULL;
gp = NULL;
if (TrapAvailable(_NewGDevice)) {
GetGWorld(&gw, &gd);
} else {
GetPort(&gp);
}
}
void Cqd3dPort::SetQDRect(Rect *r)
/*
Tell this 3dPort what portion of its 2d QuickDraw it is to draw on.
This routine does not modify the clipping region.
*/
{
Rect *vp = &vport;
long dimension = (long)(r->right - r->left +1) * (long)(r->bottom - r->top +1);
/* Set the rectangle */
vport.top = r->top;
vport.left = r->left;
vport.right = r->right;
vport.bottom = r->bottom;
/* Re-assign the zbuffer */
zbuffwidth = r->right - r->left + 1;
if (zbuff)
DisposPtr(zbuff);
zbuff = NULL;
zbufflast = NULL;
if (usezbuff) {
zbuff = (unsigned int *)NewPtr( sizeof(unsigned int) * dimension );
if (!zbuff)
lastError = noZBuffMem;
zbufflast = zbuff + dimension;
}
BuildProj();
}
void Cqd3dPort::Erase(void)
/*
Erase this entire 3dPort. Including its ZBuff.
*/
{
register unsigned int *p;
EraseRect(&vport);
if (zbuff) {
p = zbuff;
do {
*p++ = 0xffff;
} while (p < zbufflast);
}
}
Cqd3dPort *
Get3dPort(void)
/*
Returns the current 3dPort.
*/
{
return(the3dPort);
}
void Cqd3dPort::Set3dPort(void)
/*
Tell the 3d library routines, to start drawing to this 3dPort.
This routine is analogous to Quickdraw's SetPort.
Note: This routines also set's the current GWorld so that client
code doesn't have to.
*/
{
if (!(gw || gp))
Failure(true, SpecifyMsg(Qd3dStr, kNoQDEnviron));
if (gw)
SetGWorld(gw, NULL);
if (gp)
SetPort(gp);
ClipRect(&vport);
the3dPort = this;
theZBuff = this->zbuff;
theZBuffLast = this->zbufflast;
theZBuffWidth = this->zbuffwidth;
}
void Cqd3dPort::BuildTMat(void)
/*
BuildTMat builds the transformation from world coordinates to
eye coordinates matrix.
This routine should never be used by client code.
*/
{
/*
The transformation matrix derivation is from:
"Practical Techniques for Produceing 3D Graphical Images" by
Thomas A. Foley and Gregory M. Nielson (Computer Science
Department, Arizona State University) which appeared in VMEbus
Systems / November-December 1987 pp 65 - 73. The transformation
matrix is on pp 68 - 71.
*/
vector r,
va,
vb,
vc;
vvect(&f, &a, &r);
vunit(&r, &vc);
vcopy (&vc, &(tmat[2]));
vcross(&vc, &u, &r);
vunit(&r, &va);
vcopy (&va, &(tmat[0]));
vcross(&va, &vc, &vb);
vcopy(&vb, &(tmat[1]));
/* invert the matrix for matinv */
/* This is also a good time for... */
vvect(&a, &f, &r);
vunit(&r, &Ua2f);
}
void Cqd3dPort::BuildProj(void)
/*
BuildProj calculates the projection constants.
This routine should never be used by client code.
*/
{
/*
The perspective projection equations are from:
"Practical Techniques for Produceing 3D Graphical Images" by
Thomas A. Foley and Gregory M. Nielson (Computer Science
Department, Arizona State University) which appeared in VMEbus
Systems / November-December 1987 pp 65 - 73. The projection
equations are on pp 68.
*/
if (type == kqd3dPortPerspective) {
pwidth = vport.right - vport.left;
plength = vport.bottom - vport.top;
pmin = (pwidth < plength) ? pwidth : plength;
pb = (double)(pmin) / (2.0 * tan(v / 2.0));
pd = -(double)(pmin) / (2.0 * tan(v / 2.0));
pa = (vport.right + vport.left)/2;
pc = (vport.top + vport.bottom)/2;
linmap(zMin, zMax, 0.0, 1.0, &pf, &pe);
}
if (type == kqd3dPortParallel) {
double aw = ar - al, /* The eye coordinate view rectangle. */
ah = at - ab;
double bl = vport.left, /* The screen viewport rectangle. */
br = vport.right,
bt = vport.top,
bb = vport.bottom,
bw = br - bl,
bh = bb - bt;
double ayx = ah/aw,
byx = bh/bw;
double t1, t2;
if (ayx > byx) {
t1 = bh / ah;
t2 = t1 * aw;
bl = (bw - t2) / 2.0 + bl;
br = bl + t2;
} else {
t1 = bw / aw;
t2 = t1 * ah;
bt = (bh - t2) / 2.0 + bt;
bb = bt + t2;
}
linmap(al, ar, bl, br, &pb, &t1);
pa = t1;
linmap(ab, at, bb, bt, &pd, &t1);
pc = t1;
linmap(zMin, zMax, 0.0, 1.0, &pf, &pe);
}
}
void Cqd3dPort::SetView(
vector *f, /* Viewer location -- WC */
vector *a, /* Point of attention -- WC */
vector *u) /* Viewer up vector -- relative to WC */
/*
Sets the point of attention, viewer position, and viewer up vector
for this 3dPort.
*/
{
vcopy(f, &this->f);
vcopy(a, &this->a);
vcopy(u, &this->u);
BuildTMat();
return;
/* The following notice may not be removed under any
circumstance. See your licensing agreement. */
asm {
dc.b "qd3d Copyright 1991 Vividus Consulting"
}
}
void Cqd3dPort::GetView(
vector *f, /* Viewer location -- WC */
vector *a, /* Point of attention -- WC */
vector *u) /* Viewer up vector -- relative to WC */
/*
Returns the point of attention, viewer position, and viewer up vector
for this 3dPort.
*/
{
vcopy(&this->f, f);
vcopy(&this->a, a);
vcopy(&this->u, u);
}
int Cqd3dPort::GetProjectionType(void)
/*
This returns the present type of projection this 3d port performs.
*/
{
return(type);
}
void Cqd3dPort::SetPolarView(
vector *a, /* Point of attention -- WC. */
double rho, /* Distance from a -- WC distance. */
double theta, /* Theta from WC x direction in an
xy plane. */
double phi, /* Phi from WC z direction. */
double twist) /* Up vector "twist" about a->f axis
from "natural" up vector. */
/*
Set point of attention, viewer position, and viewer up vector
for this 3dPort using polar coordianates. Angle measures
(theta, phi, and twist) are in radians.
*/
{
vector f, u; /* Calculated viewer postion and up vector */
/* Get from location. */
vsphere2v (rho, phi, theta, &f);
vadd(&f, a, &f);
/* Get up vector. */
{
/*
Given the current position, center of attention, and user input up
twist this finds the up vector.
Note: Yes, this is inefficient... but it should only get called
once per rendering (at most).
Also, this doesn't take into consideration phi. Phi isn't
necessary because the generation of the transformation
matrix doesn't need cv->up to have the phi related component
in it.
*/
vector v; /* Scratch vectors. */
double p, t, /* Phi, theta. */
st, ct, /* Sines and cosines of p, t, & u. */
sp, cp,
su, cu;
double x, y, z,
x1, y1, z1;
vvect(a, &f, &v);
t = atan2(v.y, v.x);
t = -t;
st = sin(t); ct = cos(t);
su = sin(twist); cu = cos(twist);
#if 0
p = vangle(&up, &v);
x = -sp;
y = 0.0;
z = cp;
#else
x = 0.0;
y = 0.0;
z = 1.0;
x1 = x;
y1 = y*cu + z*su;
z1 = -y*su + z*cu;
x = x1*ct + y1*st;
y = -x1*st + y1*ct;
z = z1;
u.x = x;
u.y = y;
u.z = z;
#endif
}
SetView(&f, a, &u);
}
void Cqd3dPort::GetPolarView(
vector *a, /* Point of attention -- WC. */
double *rho, /* Distance from a -- WC distance. */
double *theta, /* Theta from WC x direction in an
xy plane. */
double *phi, /* Phi from WC z direction. */
double *twist) /* Up vector "twist" about a->f axis
from "natural" up vector. */
/*
Get point of attention, viewer position, and viewer up vector
for this 3dPort using polar coordianates. Angle measures
(theta, phi, and twist) are in radians.
Note: Presently, this doesn't return the twist angle.
*/
{
vector v;
vcopy(&this->a, a);
vsub(&this->f, &this->a, &v);
vv2sphere(&v, rho, phi, theta);
/* Get twist angle. */
*twist = 0.0;
}
void Cqd3dPort::SetPerspective(double v, double near, double far)
/*
Set for perspective projection with the given viewing angle (radians)
and near and far clippling planes.
Near and far can be considered distances from the eye.
Unity aspect ratio is maintained with the point of attention being
mapped to the center of the rectangle set with SetGWRect (the
viewport).
If the dy/dx ratio's of the window and viewport do not match, the
entire window specified, plus an extra amount to take up the larger
viewport area, will be mapped to the viewport.
*/
{
zMin = near;
zMax = far;
this->v = v;
type = kqd3dPortPerspective;
BuildProj();
}
void Cqd3dPort::GetPerspective(double *v, double *near, double *far)
/*
Get the perspective projection parameters.
Note: The current projection must be perspective.
*/
{
*near = zMin;
*far = zMax;
*v = this->v;
}
void Cqd3dPort::SetParallel(
vector *upperLeft,
vector *lowerRight,
double near,
double far)
/*
Set for parallel projection with the given eye coordinate rectangle
defined by upperLeft and lowerRight, and the near and far clipping
planes.
Set for perspective projection with the given viewing angle (radians)
and near and far clippling planes.
Near and far can be considered distances from the eye.
Unity aspect ratio is maintained with the point of attention being
mapped to the center of the rectangle set with SetGWRect (the
viewport).
If the dy/dx ratio's of the window and viewport do not match, the
entire window specified, plus an extra amount to take up the larger
viewport area, will be mapped to the viewport.
*/
{
zMin = near;
zMax = far;
type = kqd3dPortParallel;
al = upperLeft->x; /* The eye coordinate view rectangle. */
ar = lowerRight->x;
at = upperLeft->y;
ab = lowerRight->y;
BuildProj();
}
void Cqd3dPort::GetParallel(
vector *upperLeft,
vector *lowerRight,
double *near,
double *far)
/*
Get the parameters for the parallel projection.
Note: The current projection must be parallel and the z values of
the EC upperLeft and lowerRight are meaningless.
*/
{
*near = zMin;
*far = zMax;
upperLeft->x = al;
upperLeft->y = at;
lowerRight->x = ar;
lowerRight->y = ab;
}
int Cqd3dPort::Qd3dError(void)
/*
Returns the most recently occured qd3d error.
Note: That this routine is what resets the last reported qd3d
and not the called routines!
*/
{
int retval = lastError;
lastError = noErr;
return(retval);
}
Boolean Cqd3dPort::GetOnlyQD(void)
/*
Returns whether the "only quickdraw" flag is set.
*/
{
return(onlyqd);
}
void Cqd3dPort::SetOnlyQD(Boolean onOff)
/*
Sets the "only quickdraw" flag to onOff.
*/
{
if (onlyqd = onOff)
if (usezbuff)
SetUseZBuff(false);
}
Boolean Cqd3dPort::GetCullBacks(void)
/*
Returns whether backface culling is in affect or not.
*/
{
return(cullbacks);
}
void Cqd3dPort::SetCullBacks(Boolean onOff)
/*
Sets backface culling to onOff.
*/
{
cullbacks = onOff;
}
Boolean Cqd3dPort::GetUseZBuff(void)
/*
Returns whether z-buffer hidden surface removal is being used.
Note: That the "only quicdraw" flag will over-ride zbuffer hidden
surface removal.
*/
{
return(usezbuff);
}
void Cqd3dPort::SetUseZBuff(Boolean onOff)
/*
Sets whether z-buffer hidden surface removal will be used.
Note: The "only quickdraw" flag will over-ride zbuffer hidden
surface removal.
Note: For z-buffer hidden surface removal to function properly,
near and far in SetPerspective or SetParallel must be
set correctly.
*/
{
if (usezbuff != onOff) {
usezbuff = onOff;
SetQDRect(&vport);
}
}
Boolean Cqd3dPort::GetDepthQue(void)
/*
Returns whether depth queing is be used during drawing operations.
*/
{
return(usedepthque);
}
void Cqd3dPort::SetDepthQue(
Boolean onOff,
vector *fadeColor,
double furthestFraction)
/*
Sets depth queing to onOff.
If onOff is true, fadeColor identifies the color to fade to and
furthestFraction identifies the amount of fading to be performed
at points drawn at the far plane.
Ex: If furthestFraction = 1.0, a point drawn at the far plane will
be fadeColor. Points drawn between the far plane and the viewer
will be a linear blend between the fadeColor and the specified
drawing color. The amount of the linear blend is determined
by how close the point is to the far plane.
Note: When used in conjunction with "only quickdraw," primitive's
will be drawn with an average depth qued color.
Note: For depth queing to function properly, near and far in
SetPerspective or SetParallel must be set correctly.
*/
{
if (usedepthque = onOff) {
GetFColor(fadeColor, &dColor);
#if __option(mc68881)
{
extended ext;
x96tox80(&furthestFraction, &ext);
fFract = X2Fix(ext);
}
#else
{
extended ext;
x96tox80(&furthestFraction, &ext);
fFract = X2Fix(ext);
}
#endif
}
}
Boolean Cqd3dPort::GetWireframe(void)
/*
Returns whether fill operations are drawn using frame operations.
*/
{
return(wireframe);
}
void Cqd3dPort::SetWireframe(Boolean onOff)
/*
Sets Wireframe mode to onOff. Wireframe mode has the affect
of maping all fill drawing primitives to frame drawing primitives.
*/
{
wireframe = onOff;
}
/* ============================================================ */
/* Private transformation/projection primitives: */
Boolean
Line3dClip(
vector *p1, vector *p2, /* Input segment endpoints. */
vector *cp1, vector *cp2 /* Clipped segment endpoints. */
/* Above are in eye coordinates. */
)
/*
Clip the line segment to the current viewing volume.
If the entire segment is clipped, false is returned. Otherwise
true is returned.
Note: This is not fully implemented. See below for details.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
/*
This is a drastic clipper! If either point is beyond the near or far
plane, the entire segment is rejected.
This is an obvious candidate for a more refined implementation.
*/
register Cqd3dPort *tp = the3dPort;
if ( (p1->z < tp->zMin) || (p2->z < tp->zMin) ||
(p1->z > tp->zMax) || (p2->z > tp->zMax) )
return (false);
vcopy(p1, cp1);
vcopy(p2, cp2);
return(true);
}
Boolean
LineC3dClip(
vector *p1, vector *p2, /* Input segment endpoints. */
vector *cp1, vector *cp2, /* Clipped segment endpoints. */
/* Above are in eye coordinates. */
vector *inc1, vector *inc2, /* Input endpoint colors. */
vector *outc1, vector *outc2/* Clipped endpoint colors. */
)
/*
Clip the line segment to the current viewing volume. Endpoint
colors are also appropriately adjusted.
If the entire segment is clipped, false is returned. Otherwise
true is returned.
Note: This is not fully implemented. See below for details.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
/*
This is a drastic clipper! If either point is beyond the near or far
plane, the entire segment is rejected.
This is an obvious candidate for a more refined implementation.
*/
register Cqd3dPort *tp = the3dPort;
if ( (p1->z < tp->zMin) || (p2->z < tp->zMin) ||
(p1->z > tp->zMax) || (p2->z > tp->zMax) )
return (false);
vcopy(p1, cp1);
vcopy(p2, cp2);
vcopy(inc1, outc1);
vcopy(inc2, outc2);
return(true);
}
void
Clip3d(
int *n, /* Input & output vertice count. */
vector inndc[], /* Input polygon vertices. */
vector outndc[]) /* Clipped polygon vertices. */
/* Above are in eye coordinates. */
/*
Clip the polygon inndc to the view volume. Return the clipped
polygon in outndc and clipped polygon vertex count in n.
Note: This is not fully implemented. Se below for details.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
/*
This is a drastic clipper! If any point is beyond the near or far
plane, the entire point list is ignored (n is set to 0).
This is an obvious candidate for a more refined implementation.
*/
int i;
for (i = 0; i < *n; i++) {
if ( (inndc[i].z < the3dPort->zMin) || (inndc[i].z > the3dPort->zMax) ) {
*n = 0;
return;
}
vcopy(&inndc[i], &outndc[i]);
}
}
void
ClipC3d(
int *n, /* Input & output vertice count. */
vector inndc[], /* Input polygon vertices. */
vector outndc[], /* Clipped polygon vertices. */
/* Above are in eye coordinates. */
vector inc[], /* Input vertice colors. */
vector outc[] /* Output vertice colors. */
)
/*
Clip the polygon inndc to the view volume. Return the clipped
polygon in outndc and clipped polygon vertex count in n.
Also adjust the vertice colors identified by inc to match the
clipped polygon. Return the adjusted colors in outc.
Note: This is not fully implemented. Se below for details.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
/*
This is a drastic clipper! If any point is beyond the near or far
plane, the entire point list is ignored (n is set to 0).
This is an obvious candidate for a more refined implementation.
*/
int i;
for (i = 0; i < *n; i++) {
if ( (inndc[i].z < the3dPort->zMin) || (inndc[i].z > the3dPort->zMax) ) {
*n = 0;
return;
}
vcopy(&inndc[i], &outndc[i]);
vcopy(&inc[i], &outc[i]);
}
}
static vector tndc[PolyMaxN];
static vector t2ndc[PolyMaxN];
void
TranClipProjf(
int *n, /* Input & output vertice count. */
vector in[], /* Input polygon vertices in WC. */
FixedVector outdc[]) /* Clipped vertices in FSC. */
/*
Transform, clip and project the polygon vertice list to fixed
device screen coordinates.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
Transform(*n, in, tndc);
Clip3d(n, tndc, t2ndc);
Projectf(*n, t2ndc, outdc);
}
void
TranClipProjCf(
int *n, /* Input & output vertice count. */
vector in[], /* Input polygon vertices in WC. */
FixedVector outdc[], /* Clipped vertices in FSC. */
vector inc[], /* Input vertice colors. */
vector outc[]) /* Output vertice colors. */
/*
Transform, clip and project the polygon vertice list to fixed
device screen coordinates.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
Transform(*n, in, tndc);
ClipC3d(n, tndc, t2ndc, inc, outc);
Projectf(*n, t2ndc, outdc);
}
void
Projectf(int n, vector xe[], FixedVector xp[])
/*
Project the eye coordinates in xe to fixed viewport coordinates in xp.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
int i;
vector v;
for (i = 0; i < n; i++) {
Project(1, &xe[i], &v);
ndc2fdc(1, &v, &xp[i]);
}
}
void
ndc2fdc(int n, vector v[], FixedVector fv[])
/*
Convert the normalized viewport coordinates in v to fixed viewport
coordinates in fv.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
int i;
for (i = 0; i < n; i++) {
if (v[i].z > 1.0) v[i].z = 1.0;
if (v[i].z < 0.0) v[i].z = 0.0;
v[i].z *= 32767.0;
if (v[i].z > 32767)
Failure(true, SpecifyMsg(Qd3dStr, kZBuffBadScale));
v2fv(&v[i], &fv[i]);
}
}
void
TransformProjectf(int n, vector x[], FixedVector xt[])
/*
Transform and projects the x world coordinates to fixed viewport
coordinates.
Warning: This is a private function to the qd3d library and is
highly subject to change or removal.
*/
{
int i;
vector v;
for (i = 0; i < n; i++) {
Transform(1, &(x[i]), &v);
Projectf(1, &v, &(xt[i]));
}
}
/* ============================================================ */
/* Public transformation/projection primitives: */
void
Transform(int n, vector x[], vector xt[])
/*
Transforms the world coordinates in x to eye coordinates in xt.
*/
{
int i;
vector r;
for (i = 0; i < n; i++) {
vvect(&(the3dPort->f), &(x[i]), &r);
vmatmul( &r, the3dPort->tmat, &(xt[i]) );
}
}
void
Project(int n, vector xe[], vector xp[])
/*
Projects the eye coordinates in xe to screen coordinates in xp.
Screen coordinates are actually the GWorld coordinates.
*/
{
register int i;
register Cqd3dPort *p = the3dPort;
if (p->type == kqd3dPortPerspective) {
for (i = 0; i < n; i++) {
xp[i].x = p->pa + xe[i].x / xe[i].z * p->pb;
xp[i].y = p->pc + xe[i].y / xe[i].z * p->pd;
xp[i].z = p->pe + xe[i].z * p->pf;
/* xp[i].z = p->pe * (1.0 - p->zMin / xe[i].z);
*/ }
} else if (p->type == kqd3dPortParallel) {
for (i = 0; i < n; i++) {
xp[i].x = p->pa + xe[i].x * p->pb;
xp[i].y = p->pc + xe[i].y * p->pd;
xp[i].z = p->pe + xe[i].z * p->pf;
}
}
}
void
TransformProject(int n, vector x[], vector xt[])
/*
Tranform and projects the world coordinates in x to screen
coordinates in xt.
Screen coordinates are actually the GWorld coordinates.
*/
{
int i;
vector v;
for (i = 0; i < n; i++) {
Transform(1, &(x[i]), &v);
Project(1, &v, &(xt[i]));
}
}
void
DepthColor(FixedVector *inc, Fixed z, FixedVector *oc)
/*
Performs the depth queing color blending function on the input color,
inc at the z position in screen coordinates (the z buffer value) and
returns the result in the output color oc.
Note: If depth queing is off, oc contains inc.
*/
{
Fixed t;
FixedVector fv;
if (!the3dPort->usedepthque) {
fvcopy(inc, oc);
return;
}
z = z >> 15;
t = FixMul(z, the3dPort->fFract);
fvscale(t, &the3dPort->dColor, &fv);
t = 0x10000 - t;
fvscale(t, inc, oc);
fvadd(&fv, oc, oc);
}
/* ============================================================ */
void Cqd3dPort::DrawOrigin(double size)
/*
Draws the three coordinate axis of the world coordinates using
the current fore color. These axis are labeled. Size determines
how long to make each axis segment and is expressed in world
coordinate length. The labels are drawn at 1.1 times the distance
of size.
*/
{
vector line[2], v;
IntVector iv;
line[0].x = 0.0; line[0].y = 0.0; line[0].z = 0.0;
line[1].x = size; line[1].y = 0.0; line[1].z = 0.0;
Poly3dLine(2, line);
vscale(1.1, &line[1], &line[1]);
Qd3dError();
MoveTo3d(&line[1]);
if (Qd3dError() != moveOutVV)
DrawString("\px");
line[0].x = 0.0; line[0].y = 0.0; line[0].z = 0.0;
line[1].x = 0.0; line[1].y = size; line[1].z = 0.0;
Poly3dLine(2, line);
vscale(1.1, &line[1], &line[1]);
Qd3dError();
MoveTo3d(&line[1]);
if (Qd3dError() != moveOutVV)
DrawString("\py");
line[0].x = 0.0; line[0].y = 0.0; line[0].z = 0.0;
line[1].x = 0.0; line[1].y = 0.0; line[1].z = size;
Poly3dLine(2, line);
vscale(1.1, &line[1], &line[1]);
Qd3dError();
MoveTo3d(&line[1]);
if (Qd3dError() != moveOutVV)
DrawString("\pz");
}